'''
标准库中包含了四种队列，分别是
queue.Queue / asyncio.Queue（python3.4+）/ collections.deque / multiprocessing.Queue
'''
import collections

'''
queue.Queue和asyncio.Queue都是支持多生产者、多消费者的队列，基于collections.deque，他们都提供了Queue（FIFO队列、first in first out）、PriorityQueue（优先级队列）、LifoQueue（LIFO队列 last in first out），接口方面也相同。
区别在于queue.Queue适用于多线程的场景，
asyncio.Queue适用于协程场景下的通信，由于asyncio的加成，queue.Queue下的阻塞接口在asyncio.Queue中则是以返回协程对象的方式执行，具体差异见queue.jpg：

'''


def queue_c():
    def queue_queue():
        from queue import Queue  # LILO队列 FIFO
        q = Queue()  # 创建队列对象
        q.put(0)  # 在队列尾部插入元素
        q.put(1)
        q.put(2)
        print('**LILO队列**', q.queue)  # 查看队列中的所有元素
        print(q.get())  # 返回并删除队列头部元素
        print('**LILO队列**', q.queue)

        from queue import LifoQueue  # LIFO队列
        lifoQueue = LifoQueue()
        lifoQueue.put(1)
        lifoQueue.put(2)
        lifoQueue.put(3)
        print('**LIFO队列**', lifoQueue.queue)
        print(lifoQueue.get())  # 返回并删除队列尾部元素
        print(lifoQueue.get())
        print('**LIFO队列**', lifoQueue.queue)

        from queue import PriorityQueue  # 优先队列
        priorityQueue = PriorityQueue()  # 创建优先队列对象
        priorityQueue.put(78)  # 插入元素
        priorityQueue.put(3)  # 插入元素
        priorityQueue.put(100)  # 插入元素
        print('**优先级队列**:', priorityQueue.queue)  # 底层都是deque,打印可能不符合预期 查看优先级队列中的所有元素
        priorityQueue.put(1)  # 插入元素
        priorityQueue.put(2)  # 插入元素
        print('**优先级队列**:', priorityQueue.queue)  # 查看优先级队列中的所有元素
        print(priorityQueue.get())  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue.queue)
        print(priorityQueue.get())  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue.queue)  # 删除后剩余元素
        print(priorityQueue.get())  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue.queue)  # 删除后剩余元素
        print(priorityQueue.get())  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue.queue)  # 删除后剩余元素
        print(priorityQueue.get())  # 返回并删除优先级最低的元素
        print('全部被删除后:', priorityQueue.queue)  # 查看优先级队列中的所有元素

    def async_queue():
        import asyncio
        import janus  # python标准库之外的第三方包

        loop = asyncio.get_event_loop()  # 事件循环、驱动为协程服务
        queue = janus.Queue(loop=loop)

        def threaded(sync_q):
            for i in range(100):
                print('put %s into sync_q' % i)
                sync_q.put(i)
            sync_q.join()  # Block until all items in the queue have been gotten and processed

        async def async_coro(async_q):
            for i in range(100):
                val = await async_q.get()
                assert val == i
                print('get %s from async_q' % i)
            async_q.task_done()

        # 同步调用
        fut = loop.run_in_executor(None, threaded, queue.sync_q)
        loop.run_until_complete(fut)

        # 异步调用
        loop.run_until_complete(async_coro(queue.async_q))

        lifoQueue = janus.LifoQueue()
        s_q = lifoQueue.sync_q
        s_q.put(1)
        s_q.put(2)
        s_q.put(3)
        print('LIFO队列', lifoQueue)
        print(s_q.get())  # 返回并删除队列尾部元素
        print(s_q.get())
        print(lifoQueue)

        priorityQueue = janus.PriorityQueue().sync_q  # 创建优先队列对象
        priorityQueue.put(3)  # 插入元素
        priorityQueue.put(78)  # 插入元素
        priorityQueue.put(100)  # 插入元素
        print(priorityQueue)  # 查看优先级队列中的所有元素
        priorityQueue.put(1)  # 插入元素
        priorityQueue.put(2)  # 插入元素
        print('优先级队列:', priorityQueue)  # 查看优先级队列中的所有元素
        priorityQueue.get()  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue)
        priorityQueue.get()  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue)  # 删除后剩余元素
        priorityQueue.get()  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue)  # 删除后剩余元素
        priorityQueue.get()  # 返回并删除优先级最低的元素
        print('删除后剩余元素', priorityQueue)  # 删除后剩余元素
        priorityQueue.get()  # 返回并删除优先级最低的元素
        print('全部被删除后:', priorityQueue)  # 查看优先级队列中的所有元素

    queue_queue()
    async_queue()


def deque_c():
    q = collections.deque([1, 2, 3, 4])
    print(5 in q)  # False
    print(1 in q)  # True
    # 下玄月、逆时针
    q = collections.deque([1, 2, 3, 4])
    q.rotate(1)
    print('**deque**', q)  # [4, 1, 2, 3]
    q.rotate(1)
    print('**deque**', q)  # [3, 4, 1, 2]

    # 上玄月、顺时针
    q = collections.deque([1, 2, 3, 4])
    q.rotate(-1)
    print('**deque**', q)  # [2, 3, 4, 1]
    q.rotate(-1)
    print('**deque**', q)  # [3, 4, 1, 2]

    dequeQueue = collections.deque(['Eric', 'John', 'Smith'])
    print(dequeQueue)
    dequeQueue.append('Tom')  # 在右侧插入新元素
    dequeQueue.appendleft('Terry')  # 在左侧插入新元素
    print(dequeQueue)
    dequeQueue.rotate(2)  # 循环右移2次
    print('循环右移2次后的队列', dequeQueue)
    dequeQueue.popleft()  # 返回并删除队列最左端元素
    print('删除最左端元素后的队列：', dequeQueue)
    dequeQueue.pop()  # 返回并删除队列最右端元素
    print('删除最右端元素后的队列：', dequeQueue)


if __name__ == '__main__':
    deque_c()
    queue_c()
    '''
    multiprocessing.Queue既是线程安全也是进程安全的，相当于queue.Queue的多进程克隆版
    multi_process_pool.py 中run_communication展示了
    '''
